package com.xbai.security.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;

import javax.sql.DataSource;

/**
 * @author xbai
 * @Date 2021/4/17
 */
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    private DataSource dataSource;

    @Bean
    public PersistentTokenRepository persistentTokenRepository() {
        JdbcTokenRepositoryImpl repository = new JdbcTokenRepositoryImpl();
        repository.setDataSource(dataSource);
        //设置启动的时候创建表
//        repository.setCreateTableOnStartup(true);
        return repository;
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // 退出登录
        http.logout().logoutUrl("/logout").logoutSuccessUrl("/test/hello").permitAll();
        // 配置没有权限访问跳转自定义页面
        http.exceptionHandling().accessDeniedPage("/unauth.html");
        //表单登录
        http.formLogin()
                // 自定义编写的登录页面
                .loginPage("/login.html")
                // 登录访问路径
                .loginProcessingUrl("/user/login")
                // 登录成功之后，跳转路径
                .defaultSuccessUrl("/success.html")
                // 登录失败跳转路径
                .failureForwardUrl("/fail")
                .permitAll()
                //认证配置
                .and().authorizeRequests()
                // 设置可以直接访问的路径，不需要认证
                .antMatchers("/test/hello", "/user/login").permitAll()
                // 当前登录用户，只有具有 admin 权限才可以访问这个路径
//                .antMatchers("/test/index").hasAuthority("admin")
                // hasAnyAuthority
//                .antMatchers("/test/index").hasAnyAuthority("admin,manager")
                .antMatchers("/test/index").hasRole("管理员")
                .antMatchers("/test/index").hasAnyAuthority("menu:system")
                //其他请求
                .anyRequest()
                //都需要身份认证
                .authenticated()
                // 自动登录
                .and().rememberMe().tokenRepository(persistentTokenRepository())
                // 设置有效时长，单位秒
                .tokenValiditySeconds(60)
                .userDetailsService(userDetailsService);
        // 关闭 csrf 防护
        http.csrf().disable();
    }


    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        /*String password = passwordEncoder().encode("123456");
        auth.inMemoryAuthentication()
                .withUser("zhangsan")
                .password(password)
                .roles("admin");*/
        auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}
